"""
cmd命令工具
@date 2019/12/28
@author hujing
"""
import os
import subprocess
import threading
from queue import Queue, Empty


class Command:

    # 命令的结束标志
    end_sign = 'END'

    def __init__(self, response_call, error_call=None):
        """
        :param response_call: 返回结果的回调函数
        :param error_call: 错误结果的回调函数
        """
        self.popen = None
        self.error_call = error_call
        self.response_call = response_call
        self.init_popen()
        # 启动读取输出的现成
        self.response_thread = threading.Thread(target=self.read_response)
        self.response_thread.start()
        if error_call:
            self.error_thread = threading.Thread(target=self.read_error)
            self.error_thread.start()

    def init_popen(self):
        self.popen = subprocess.Popen('/bin/bash', shell=True, stdin=subprocess.PIPE, stderr=subprocess.PIPE,
                                      stdout=subprocess.PIPE)

    def read_response(self):
        """
        循环读取输出缓冲区，将结果内容放到本地队列中
        """
        response = ''
        while True:
            line = self.popen.stdout.readline()
            if not line:
                continue
            line = line.decode('utf8')
            if line.strip() == self.end_sign:
                self.response_call(response)
                response = ''
            else:
                response += line

    def read_error(self):
        """
        循环读取错误内容, 将结果内容放到本地队列中
        :return:
        """
        while True:
            line = self.popen.stderr.readline()
            if not line:
                continue
            self.error_call(line.decode('utf8'))

    def exec_command(self, comm):
        """
        运行cmd命令
        :param comm:
        :return:
        """
        if self.popen.poll() is not None:
            self.init_popen()
        comm += os.linesep
        self.popen.stdin.write(comm.encode('utf8'))
        self.popen.stdin.write(('echo ' + self.end_sign + os.linesep).encode('utf8'))
        self.popen.stdin.flush()

    def close(self):
        self.popen.stdin.close()
        self.popen.stdout.close()
        self.popen.stderr.close()
        self.response_thread.join(timeout=1)
        if self.error_thread:
            self.error_thread.join(timeout=1)


if __name__ == '__main__':
    c = Command(lambda str: print(str), lambda s: print(s))
    while True:
        s = input()
        c.exec_command(s)

